<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>util</title>
</head>
<body>
   <main>
    <p>请输入:</p>
    <input type="text" id="input">
    <p id="p"></p>
    <button id='button'>0</button>
  </main>

</body>
<script>
  // 函数柯里化
  var curry = fn =>
  judge = (...args) =>
    args.length === fn.length
      ? fn(...args)
      : (...arg) => judge(...args, ...arg)

  function curry(fn, oldArgs) {
    const args = oldArgs || []
    const length = fn.length
    return function () {
      const _args = args.concat([].slice.call(arguments))
      if (_args.length < fn.length) {
        return curry.call(this, fn, _args)
      } else {
        return fn.apply(this, _args)
      }
    }
  }

  var fn = curry(function (a, b, c) {
    console.log([a, b, c]);
  });

  fn()("a", "b", "c") // ["a", "b", "c"]
  fn("a", "b")("c") // ["a", "b", "c"]
  fn("a")("b")("c") // ["a", "b", "c"]
  fn("a")("b", "c") // ["a", "b", "c"]

  var memoize = function (func, hasher) {
    var memoize = function (key) {
      var cache = memoize.cache
      var address = hasher ? hasher.apply(this, arguments) : key
      if (!cache[address]) {
        cache[address] = func.apply(this, arguments)
      }
      return cache[address]
    }
    memoize.cache = {}
    return memoize
  }

  // 防抖
  function debounce(fn, delay) {
    const timer = null
    return function (...args) {
      const that = this
      clearTimeout(timer)
      timer = setTimeout(function () {
        fn.apply(that, args)
      }, delay)
    }
  }

  // 节流
  function throttle(fn, delay = 500) {
    const starTime = 0
    return function (...args) {
      const endTime = new Date().getTime()
      if (endTime - starTime > delay) {
        starTime = endTime
        fn.apply(this, args)
      }
    }
  }

  // 深拷贝
  function deepclone(parent) {
    if (typeof parent !== "object") {
      return
    }
    const obj = Array.isArray(parent) ? [] : {}
    for (const key in parent) {
      if (parent.hasOwnProperty(key)) {
        const element = parent[key];
        obj[key] = typeof element === 'object' ? deepclone(element) : element
      }
    }
    return obj
  }

  // instance of
  // 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
  function instance_of(L, R) {
    const O = R.prototype;
    L = L.__proto__;

    while (true) {
        if (L === null) return false;
        if (O === L) return true;
        L = L.__proto__;
    } 
  }

    // event bus
  function EventEmeitter() {
    this._events = {}
  }

  EventEmeitter.prototype.addListener = function (type, fn) {
    if (!this._events[type]) {
      this._events[type] = fn
    }
  }

  EventEmeitter.prototype.emit = function (type) {
    var handler = this._events[type]
    var args = [].slice.call(arguments)
    if (handler) {
      return handler.apply(this, args)
    }
  }

  // new
  function createInstance() {
    var obj = new Object()
    var constructor = [].slice.call(arguments, 0, 1)
    var args = [].slice.call(arguments, 1)
    obj.__proto__ = Object.create(constructor.prototype)
    var ret = constructor.apply(obj, args)
    return typeof ret === 'object' ? ret : obj
  }

  // call
  function myCall(context) {
    const obj = context || window
    const args = [].prototype.slice.call(arguments, 1)
    obj.fn = this
    const result = obj.fn(...args)
    delete obj.fn
    return result
  }

  // apply
  function myApply(context, args) {
    const obj = context || window
    obj.fn = this
    const result = obj.fn(...args)
    delete obj.fn
    return result
  }

  // bind
  function myBind(fn) {
    const initArgs = [].prototype.slice.call(arguments, 1)
    return function () {
      const args = initArgs.concat([].prototype.slice(arguments))
      return fn.apply(this, args)
    }
  }

  // object.create
  function create(proto) {
    function F() { }
    F.prototype = proto
    return new F()
  }

  // JSON.parse
  function myParse(json) {
    return eval("(" + json + ")")
  }

  // 类的继承
  function Parent(name) {
    this.parent = name
  }

  Parent.prototype.say = function () {
    console.log(`${this.parent}: 你打篮球的样子像kunkun`)
  }

  function Child(name, parent) {
    Parent.call(this, parent)
    this.child = name
  }

  Child.prototype = Object.create(Parent.prototype)
  Child.prototype.say = function () {
    console.log(`${this.parent}好，我是练习时长两年半的${this.child}`);
  }
  Child.prototype.constructor = Child

  var parent = new Parent('father');
  parent.say() // father: 你打篮球的样子像kunkun

  var child = new Child('cxk', 'father');
  child.say() // father好，我是练习时长两年半的cxk

/* 平铺数组，depth为需要平铺的层级
 * const array = [1, [2, [3, [4]], 5]]
 * flattenDepth(array, 1)
 * // => [1, 2, [3, [4]], 5]
 * flattenDepth(array, 2)
 * // => [1, 2, 3, [4], 5]
 */
function flattenDepth(array, depth) {
  if(depth === 0) {
    return array
  }
  const arr = []
  for(let i = 0; i<array.length; i++) {
    if(Array.isArray(array[i])) {
      arr.push(...array[i])
    } else {
      arr.push(array[i])
    }
  }
  depth--
  return flattenDepth(arr, depth)
}
// 实现一个函数，根据路径输出对象或数组当中的值
// const obj = {a:[{b:{c:3}}]},path1 = 'a.0.b.c'
// const arr = [{a:{b:[{c:1}]}}],path2 = '0.a.b.0.c'
function getValueFromPath(obj, path) {
  const paths = path.split('.')
  let res = obj
  let prop
  while(prop = paths.shift()) {
    res = res[prop]
  }
  return res
}

// 有效的括号
function isValid(s) {
  const stack = []
  for (const v of s) {
    switch (v) {
      case '(':
        stack.push(')')
        break;
      case '[':
        stack.push(']')
        break;
      case '{':
        stack.push('}')
        break;
      default:
        if(stack.pop() !== v) {
          return false
        }
    }
  }
  return stack.length === 0
}

// 一个数组，判断是否有下标为 
// i, j, k 的三个数字递增，
// 且 i < j < k
function increasingTriplet(nums) {
  if(nums.length < 3) {
    return false
  }
  let one = undefined
  let two = undefined
  for(let i = 0; i<nums.length; i++) {
    if(nums[i] > two) {
      return true
    } else if (nums[i] > one) {
      two = nums[i]
    } else {
      one = nums[i]
    }
  }
  return false
}

// a_k 的键转为 aK
function toConvert(data) {
  if(typeof data !== "object" || !data) {
    return data
  }
  if(Array.isArray(data)) {
    return data.map(item => toConvert(item))
  }
  const newData = {}
  for (const key in data) {
    if (Object.hasOwnProperty.call(data, key)) {
      let newKey = key.replace(/_([a-z])/g, res => res[1].toUpperCase())
      newData[newKey] = toConvert(data[key])
    }
  }
  return newData
}

// 长度最小的子数组，滑动窗口
// 输入：s = 7, nums = [2,3,1,2,4,3] 输出：2 解释：子数组 [4,3] 是该条件下的长度最小的子数组。
var minSubArrayLen = function(target, nums) {
    let start, end
    start = end = 0
    let sum = 0
    let len = nums.length
    let ans = Infinity
    
    while(end < len){
        sum += nums[end];
        while (sum >= target) {
          ans = Math.min(ans, end - start + 1);
          sum -= nums[start];
          start++;
        }
        end++;
    }
    return ans === Infinity ? 0 : ans
};


</script>
</html>
